/**
 * @file pressure.c
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include "lv_watch.h"

#if USE_LV_WATCH_ELEVATION!= 0

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/


/**********************
 *  STATIC VARIABLES
 **********************/
static uint32_t pressure_data[ELEVATION_W];
static elevation_mng_t pressure_mng = {};
/**********************
 *      MACROS
 **********************/

/**********************
 *   STATIC FUNCTIONS
 **********************/
static void pressure_test_init(void)
{
    uint32_t i, j;
    int8_t z;

    j = 300;

#if LV_WATCH_SIMULATOR_360 == 1
    for(i = 0; i < ELEVATION_W - 230; i++) {
#else
    for(i = 0; i < ELEVATION_W - 120; i++) {
#endif
        if(j == 300) z = 10;
        if(j == 800) z = -5;

        j+=z;
        pressure_data[i] = j;
    }

#if LV_WATCH_SIMULATOR_360 == 1
    for(; i < ELEVATION_W - 200; i++) {
#else
    for(; i < ELEVATION_W - 100; i++) {
#endif
        pressure_data[i] = 500 - i;
    }

    j = 300;
    for(; i < ELEVATION_W; i++) {
        if(j == 300) z = 10;
        if(j == 800) z = -5;

        j+=z;
        pressure_data[i] = j;
    }

}

static uint32_t pressure_get_data(uint32_t x)
{
    return (ELEVATION_HOR * pressure_data[x]) / PRESSURE_GOAL_STEP;
}

static void pressure_add_record(lv_obj_t * canvas, uint32_t x, lv_color_t start, lv_color_t end)
{
    uint32_t i, h, h_before, offset = 1;
    uint32_t mix;
    lv_color_t act_color;
    lv_obj_t * highest_dot;
    lv_obj_t * lowest_dot;
    uint32_t posx = x;
    if(lv_obj_get_base_dir(canvas) == LV_BIDI_DIR_RTL)
        posx = ELEVATION_W - x - 1;

    h = pressure_get_data(x);
     if(lv_watch_get_activity_obj(ACT_ID_ELEVATION) != NULL) {
         lv_elevation_obj_ext_t * ext = elevation_pressure_get_ext();
         highest_dot = ext->pressure_ext.highest_dot;
         lowest_dot = ext->pressure_ext.lowest_dot;
     }
#if USE_LV_WATCH_LAUNCHER2 != 0
     else {
         lv_launcher_pressure_tab_ext_t * ext = lv_obj_get_ext_attr(launcher_get_tab(TAB_APP_PRESSURE));
         highest_dot = ext->pressure_ext.highest_dot;
         lowest_dot = ext->pressure_ext.lowest_dot;
     }
#endif

    if(pressure_data[x] >= pressure_data[pressure_mng.highest_x]) {
        pressure_mng.highest_x = x;
        lv_obj_align(highest_dot, canvas, LV_ALIGN_IN_TOP_LEFT, posx - lv_obj_get_width(highest_dot) / 2,
                     ELEVATION_HOR - h - lv_obj_get_width(highest_dot) / 2);
    }

    if((pressure_data[x] <= pressure_data[pressure_mng.lowest_x]) && (pressure_data[x] != 0)) {
        pressure_mng.lowest_x = x;
        lv_obj_align(lowest_dot, canvas, LV_ALIGN_IN_TOP_LEFT, posx - lv_obj_get_width(lowest_dot) / 2,
                     ELEVATION_HOR - h - lv_obj_get_width(lowest_dot) / 2);
    }

    if(x != 0) {
        h_before = pressure_get_data(x - 1);
        if(h_before == h)
            offset = 1;
        else if(h_before < h)
            offset = h - h_before;
        else
            offset = h_before -h;
    } else {
        h_before = h;
    }

    if(h_before <= h) {
        for(i = ELEVATION_HOR - 1; i > ELEVATION_HOR - h + offset; i--) {
            mix = ((h - (ELEVATION_HOR - i)) * 255) / h;
            act_color = lv_color_mix(start, end, mix);
            lv_canvas_set_px(canvas, posx, i, act_color);
        }

        for(; i > ELEVATION_HOR - h; i--) {
            lv_canvas_set_px(canvas, posx, i, LV_COLOR_BLUE);
        }
    } else {
        for(i = ELEVATION_HOR - 1; i > ELEVATION_HOR - h; i--) {
            mix = ((h - (ELEVATION_HOR - i)) * 255) / h;
            act_color = lv_color_mix(start, end, mix);
            lv_canvas_set_px(canvas, posx, i, act_color);
        }

        for(; i > ELEVATION_HOR - h - offset; i--) {
            lv_canvas_set_px(canvas, posx, i, LV_COLOR_BLUE);
        }
    }
}

static void pressure_update_display(lv_obj_t * obj, uint32_t x)
{
    char str[20] = {};
    lv_obj_t * pressure_canvas = NULL;
    lv_obj_t * pressure_goal = NULL;
    lv_obj_t * current_rate = NULL;
    lv_obj_t * highest_rate = NULL;
    lv_obj_t * lowest_rate = NULL;

    if(lv_watch_get_activity_obj(ACT_ID_ELEVATION) != NULL) {
        lv_elevation_obj_ext_t * ext = elevation_pressure_get_ext();
        pressure_canvas = ext->pressure_ext.pressure_canvas;
        pressure_goal = ext->pressure_ext.pressure_goal;
        current_rate = ext->pressure_ext.current_rate;
        highest_rate = ext->pressure_ext.highest_rate;
        lowest_rate = ext->pressure_ext.lowest_rate;
    }
#if USE_LV_WATCH_LAUNCHER2 != 0
    else {
        lv_launcher_pressure_tab_ext_t * ext = lv_obj_get_ext_attr(launcher_get_tab(TAB_APP_PRESSURE));
        pressure_canvas = ext->pressure_ext.pressure_canvas;
        pressure_goal = ext->pressure_ext.pressure_goal;
        current_rate = ext->pressure_ext.current_rate;
        highest_rate = ext->pressure_ext.highest_rate;
        lowest_rate = ext->pressure_ext.lowest_rate;
    }
#endif

    pressure_add_record(pressure_canvas, x , LV_COLOR_BLACK, LV_COLOR_BLUE);
    lv_obj_invalidate(pressure_canvas);

    snprintf(str, 20, "%d %s", pressure_data[x] + 300, (char *)lv_lang_get_text(WATCH_TEXT_ID_HPA));
    lv_label_set_text(current_rate, str);

    memset(str, 0, 20);
    snprintf(str, 20, "%d", pressure_data[pressure_mng.highest_x] + 300);
    lv_label_set_text(highest_rate, str);

    memset(str, 0, 20);
    snprintf(str, 20, "%d", pressure_data[pressure_mng.lowest_x] + 300);
    lv_label_set_text(lowest_rate, str);

    float delta =  (float)pressure_data[x]/ PRESSURE_GOAL_STEP;
    int16_t val = delta * (ELEVATION_CIRCLE_END - ELEVATION_CIRCLE_START) + ELEVATION_CIRCLE_START + 900;
    int16_t val_sub = val % 3600;
    if((val_sub < ELEVATION_CIRCLE_START + 900) && (val_sub > 600)) val = 600;
    lv_img_set_angle(pressure_goal, val);
}

static void pressure_update_task(lv_anim_t *a)
{
    pressure_update_display(a->var, pressure_mng.current_x);
    if(pressure_mng.current_x != ELEVATION_W - 1)
        pressure_mng.current_x++;
}

static void pressure_update_start(lv_obj_t * obj)
{
    uint16_t i;

    printf("currentx %d\n", pressure_mng.current_x);
    for(i = 0; i < pressure_mng.current_x; i++) {
        pressure_update_display(obj, i);
    }

    lv_anim_t a;
    lv_anim_init(&a);
    lv_anim_set_var(&a, obj);
    lv_anim_set_time(&a, 1);
    lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
    lv_anim_set_repeat_delay(&a, ELEVATION_UPDATE_PERIOD);       // update every 1s
    lv_anim_set_start_cb(&a, pressure_update_task);
    lv_anim_start(&a);
}

static void pressure_add_element(lv_obj_t * tab, pressure_ext_t * ext)
{
    lv_obj_t * tileview = lv_obj_get_parent(tab);
    lv_obj_t * img_color_circle = lv_img_create(tab, NULL);
    LV_ASSERT_MEM(img_color_circle);
    if(img_color_circle == NULL) return;
    lv_img_set_src(img_color_circle, ICON_COLOR_CIRCLE);
    lv_img_set_zoom(img_color_circle,LV_IMG_ZOOM_NONE * lv_obj_get_width(tab) / 240);
    lv_obj_add_style(img_color_circle, LV_IMG_PART_MAIN, &lv_watch_image);
    lv_obj_align(img_color_circle, tab, LV_ALIGN_CENTER, 0, 0);
    lv_obj_t * pressure_goal = lv_img_create(tab, NULL);
    lv_img_set_src(pressure_goal, ICON_STEP_DOT);
    lv_img_set_zoom(pressure_goal,LV_IMG_ZOOM_NONE * lv_obj_get_width(tab) / 240);
    lv_coord_t img_w = lv_obj_get_width(pressure_goal);
    lv_coord_t tab_w = lv_obj_get_width(tab);
    lv_coord_t radius = 0;
    if(tab_w > 240)
    {
        radius = tab_w / 2 - 33 - img_w / 2;
    }
    else
    {
        radius = tab_w / 2 - 18 * tab_w / 240 - img_w / 2;
    }

    lv_coord_t pivot_x = radius * 240 / tab_w;
    lv_img_set_pivot(pressure_goal,
                     -pivot_x,
                     lv_obj_get_height(pressure_goal) / 2);
    lv_obj_align(pressure_goal, tab, LV_ALIGN_IN_RIGHT_MID,
                 radius * 240 / tab_w + img_w - tab_w / 2, 0);

    ext->pressure_canvas = NULL;
    ext->current_rate = NULL;
    ext->highest_rate = NULL;
    ext->lowest_rate = NULL;
    ext->highest_dot = NULL;
    ext->lowest_dot = NULL;
    ext->pressure_goal = pressure_goal;

    lv_obj_t * label_content1 = lv_cont_create(img_color_circle, NULL);
    lv_obj_add_style(label_content1, LV_OBJ_PART_MAIN, &lv_watch_style_transp);
    lv_obj_set_size(label_content1, 100,60);
    lv_cont_set_layout(label_content1, LV_LAYOUT_COLUMN_MID);
    lv_obj_t * current_rate = lv_label_create(label_content1, NULL);
    lv_obj_add_style(current_rate,LV_LABEL_PART_MAIN, &lv_watch_font20_gray);
    lv_obj_set_size(current_rate, 100,20);
    lv_label_set_text_id(current_rate, WATCH_TEXT_ID_PRESSURE);
    //add current rate

    char str[20];
    current_rate = lv_label_create(label_content1, NULL);
    lv_obj_add_style(current_rate,LV_LABEL_PART_MAIN, &lv_watch_font20_yellow);
    ext->current_rate = current_rate;
    lv_obj_set_size(current_rate, 100,20);
    snprintf(str, 20, "%d %s", 0, (char *)lv_lang_get_text(WATCH_TEXT_ID_HPA));
    lv_label_set_text(current_rate, str);
    lv_obj_align(label_content1, img_color_circle, LV_ALIGN_CENTER, 0, -90);

    lv_obj_t * pressure_content = lv_cont_create(img_color_circle, NULL);
    lv_obj_add_style(pressure_content, LV_OBJ_PART_MAIN, &lv_watch_style_transp);
    lv_obj_set_size(pressure_content, ELEVATION_W, ELEVATION_HOR);
    lv_obj_align(pressure_content, label_content1, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);

    uint8_t color_size = lv_img_cf_get_px_size(LV_IMG_CF_TRUE_COLOR);
    uint32_t buff_size = (color_size * ELEVATION_W * ELEVATION_HOR) / 8;
    uint8_t * canvas_buff = lv_mem_alloc(buff_size);
    memset(canvas_buff, 0, buff_size);

    lv_obj_t * pressure_canvas = lv_canvas_create(pressure_content, NULL);
    ext->pressure_canvas = pressure_canvas;
    lv_obj_set_size(pressure_canvas, ELEVATION_W, ELEVATION_HOR + 10);
    lv_canvas_set_buffer(pressure_canvas, canvas_buff, ELEVATION_W, ELEVATION_HOR, LV_IMG_CF_TRUE_COLOR);
    lv_obj_align(pressure_canvas, pressure_content, LV_ALIGN_IN_BOTTOM_LEFT, 0, -15);

    //add axis-x
    elevation_add_axis_x(pressure_content, pressure_canvas);
    lv_obj_t * highest_dot_img = lv_img_create(pressure_canvas, NULL);
    ext->highest_dot = highest_dot_img;
    lv_img_set_src(highest_dot_img, ICON_HEART_RATE_HIGHEST_DOT);

    lv_obj_t * lowest_dot_img = lv_img_create(pressure_canvas, NULL);
    ext->lowest_dot = lowest_dot_img;
    lv_img_set_src(lowest_dot_img, ICON_HEART_RATE_LOWEST_DOT);

    lv_obj_t * label_content2 = lv_cont_create(img_color_circle, NULL);
    lv_obj_add_style(label_content2, LV_OBJ_PART_MAIN, &lv_watch_style_transp);
    lv_obj_set_size(label_content2, 100,30);
    lv_cont_set_layout(label_content2, LV_LAYOUT_ROW_MID);

    lv_obj_t * highest_img = lv_img_create(label_content2, NULL);
    lv_img_set_src(highest_img, ICON_ELEVATION_HIGHEST);
    //add highest rate
    lv_obj_t * highest_rate = lv_label_create(label_content2, NULL);
    ext->highest_rate = highest_rate;
    lv_obj_set_style_local_text_font(highest_rate, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_THEME_WATCH_NIGHT_FONT_30);
    lv_obj_set_style_local_text_color(highest_rate, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);

    lv_label_set_text(highest_rate, "0");

    lv_obj_align(label_content2, pressure_content, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);

    lv_obj_t * label_content3 = lv_cont_create(img_color_circle, NULL);
    lv_obj_add_style(label_content3, LV_OBJ_PART_MAIN, &lv_watch_style_transp);
    lv_obj_set_size(label_content3, 100,30);
    lv_cont_set_layout(label_content3, LV_LAYOUT_ROW_MID);

    lv_obj_t * lowest_img = lv_img_create(label_content3, NULL);
    lv_img_set_src(lowest_img, ICON_ELEVATION_LOWEST);
    //add lowest rate
    lv_obj_t * lowest_rate = lv_label_create(label_content3, NULL);
    ext->lowest_rate = lowest_rate;
    lv_obj_set_style_local_text_font(lowest_rate, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_THEME_WATCH_NIGHT_FONT_30);
    lv_obj_set_style_local_text_color(lowest_rate, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
    lv_label_set_text(lowest_rate, "0");
    lv_obj_align(label_content3, label_content2, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);

#if ELEVATION_TEST
    pressure_test_init();
#endif

    pressure_update_start(tab);
    lv_tileview_add_element(tileview, pressure_goal);
    lv_tileview_add_element(tileview, img_color_circle);
    lv_tileview_add_element(tileview, pressure_content);
    lv_tileview_add_element(tileview, label_content1);
    lv_tileview_add_element(tileview, label_content2);
    lv_tileview_add_element(tileview, label_content3);

    lv_obj_set_click(pressure_goal, false);
    lv_obj_set_click(img_color_circle, false);
    lv_obj_set_click(pressure_content, false);
    lv_obj_set_click(label_content1, false);
    lv_obj_set_click(label_content2, false);
    lv_obj_set_click(label_content3, false);
}

/**********************
 *   GLOBAL FUNCTIONS
***********************/
#if USE_LV_WATCH_LAUNCHER2 != 0
void pressure_create_tab(lv_obj_t * par)
{
    lv_launcher_pressure_tab_ext_t * ext = lv_obj_allocate_ext_attr(par, sizeof(lv_launcher_pressure_tab_ext_t));
    pressure_add_element(par, &(ext->pressure_ext));
}
#endif

lv_obj_t * pressure_create(lv_obj_t * tileview, uint16_t id)
{
    lv_obj_t * tab = elevation_pressure_tileview_add_tile(tileview, id);
    LV_ASSERT_MEM(tab);
    if(tab == NULL) return NULL;

    lv_elevation_obj_ext_t * ext = elevation_pressure_get_ext();
    pressure_add_element(tab, &(ext->pressure_ext));

    lv_obj_t * label_content4 = lv_cont_create(tab, NULL);
    lv_obj_add_style(label_content4, LV_OBJ_PART_MAIN, &lv_watch_style_transp);
    lv_obj_set_size(label_content4, 30,30);
    lv_cont_set_layout(label_content4, LV_LAYOUT_OFF);
    lv_obj_t * label_up = lv_label_create(label_content4, NULL);
    lv_label_set_text(label_up, LV_SYMBOL_DOWN);
    lv_obj_align(label_up, label_content4, LV_ALIGN_CENTER, 0, 0);
    lv_obj_align(label_content4, tab, LV_ALIGN_IN_BOTTOM_MID, 0, -5);
    lv_tileview_add_element(tileview, label_content4);
    lv_obj_set_click(label_content4, false);

    return tab;
}

#endif /*USE_LV_WATCH_ELEVATION*/
